using System.Collections.Concurrent;

namespace ConsoleApp1;

public class Record
{
    public string Name { get; set; }

    public int Id { get; set; }
    public string Value { get; set; }

    public string Remark { get; set; }
}

public class MultiThreadParseFile
{
    public static List<Record> ParseFile1(string filePath)
    {
        var records = new ConcurrentBag<Record>();
        var lines = File.ReadLines(filePath);

        Parallel.ForEach(lines, line =>
        {
            //使用正则 tab 空格 等
            var parts = line.Split(" ");
            if (parts.Length >= 4)
            {
                records.Add(new Record
                {
                    Name = parts[0],
                    Id = int.Parse(parts[1]),
                    Value = parts[2],
                    Remark = parts[3]
                });
            }
        });

        return new List<Record>(records);
    }

    public static async Task ParseFiles2(string[] args)
    {
        string filePath = "path_to_your_large_file.txt";
        var records = await MultiThreadParseFile.ParseFileAsync(filePath);
        Console.WriteLine($"Total records parsed: {records.Count}");
    }

    public static async Task<List<Record>> ParseFileAsync(string filePath, int chunkSize = 1024 * 1024)
    {
        var records = new List<Record>();
        var tasks = new List<Task<List<Record>>>();


        await using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            var buffer = new byte[chunkSize];
            int bytesRead;
            // long position = 0;
            while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
            {
                var chunk = new string(System.Text.Encoding.UTF8.GetChars(buffer, 0, bytesRead));
                var task = Task.Run(() => ParseChunk(chunk));
                tasks.Add(task);
                // position += bytesRead;
            }
        }

        var results = await Task.WhenAll(tasks);
        foreach (var result in results)
        {
            records.AddRange(result);
        }

        return records;
    }

    private static List<Record> ParseChunk(string chunk)
    {
        var records = new List<Record>();
        var lines = chunk.Split(new[] { ' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);

        Record currentRecord = null;

        foreach (var item in lines)
        {
            var parts = item.Split('=');
            if (parts.Length != 2) continue;

            var key = parts[0].ToLower();
            var value = parts[1];

            switch (key)
            {
                case "name":
                    if (currentRecord != null) records.Add(currentRecord);
                    currentRecord = new Record { Name = value };
                    break;
                case "id":

                    if (currentRecord != null && int.TryParse(value, out var id))
                        currentRecord.Id = id;
                    // if (currentRecord != null)
                    // {
                    //     var number = int.Parse(value);
                    //     currentRecord.Id = number;
                    // }

                    break;
                case "value":
                    if (currentRecord != null)
                        currentRecord.Value = value;
                    break;
                case "remark":
                    if (currentRecord != null)
                        currentRecord.Remark = value;
                    break;
            }
        }

        if (currentRecord != null) records.Add(currentRecord);

        return records;
    }
}